package Simulation;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.image.BufferedImage;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;

class MainEngine {
	public static void main(String[] args){
		new MainEngine();
	}
	public int XCords = 100;
	public int YCords = 100;
	public Gate[][] map = new Gate[XCords][YCords];
	public Image[][] mapping = new Image[20][20];
	public int X = Math.round(XCords/2);
	public int Y = Math.round(YCords/2);
	public final JFrame viewer = new JFrame();
	public MainEngine(){
		viewer.setSize(700,700);
		viewer.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		viewer.setResizable(false);
		//Define View
		JSplitPane pane = new JSplitPane();
		//Add mapView as Map
		JPanel mapView = new JPanel();
		GridLayout test = new GridLayout(20,20);
		mapView.setLayout(test);
		mapView.setSize(1000,1000);
		JPanel[][] mapParts = new JPanel[20][20];
		for (int xi = 0;xi<mapParts.length;xi++){
			for (int yi = 0;yi<mapParts[xi].length;yi++){
				final int xi2 = xi;
				final int yi2 = yi;
				mapParts[xi][yi] = new JPanel(){
					public void paint(Graphics g){
						g.drawImage(mapping[xi2][yi2],0,0,this.getWidth(),this.getHeight(),this);
					}
				};
				final MainEngine backup = this;
				mapParts[xi][yi].addMouseListener(new MouseListener(){

					@Override
					public void mouseClicked(MouseEvent arg0) {
						// TODO Auto-generated method stub
						if (map[X+xi2][Y+yi2]!=null){
							map[X+xi2][Y+yi2].click();
						}
					}

					@Override
					public void mouseEntered(MouseEvent arg0) {
						// TODO Auto-generated method stub
						
					}

					@Override
					public void mouseExited(MouseEvent arg0) {
						// TODO Auto-generated method stub
						
					}

					@Override
					public void mousePressed(MouseEvent arg0) {
						// TODO Auto-generated method stub
					}

					@Override
					public void mouseReleased(MouseEvent arg0) {
						// TODO Auto-generated method stub
						if (arg0.isPopupTrigger()){
							GateSelect menu = new GateSelect(X+xi2,Y+yi2,backup);
							if (map[X+xi2][Y+yi2]!=null){
								menu.add(map[X+xi2][Y+yi2].getMenu());
							}
							menu.show(arg0.getComponent(),arg0.getX(),arg0.getY());
						}
					}
					
				});
				mapParts[xi][yi].setPreferredSize(new Dimension(50,50));
				mapView.add(mapParts[xi][yi]);
			}
		}
		pane.setLeftComponent(new JScrollPane(mapView));
		//Add OptionPane as Gear
		JPanel OptionPane = new JPanel();
		pane.setRightComponent(new JScrollPane(OptionPane));
		//add pane
		viewer.add(pane);
		//View
		viewer.show();
		//render
		Thread reRender = new Thread(){
			public void run(){
				long lastTime = System.currentTimeMillis();
				long lastSet = 0;
				int fps = 30;
				int cc = 1;
				long fc = 1000/(fps+1);
				while (true){
					if (cc<=fps){
						if (fc*cc<System.currentTimeMillis()-lastTime){
							for (int I=0;I<mapping.length;I++){
								for (int I2=0;I2<mapping[I].length;I2++){
									if (map[X+I][Y+I2]!=null){
										mapping[I][I2] = map[X+I][Y+I2].paint();
									}else{
										mapping[I][I2] = Gate.paintClear();
									}
								}
							}
							for (int XCur = 0;XCur<XCords;XCur++){
								for (int YCur = 0;YCur<YCords;YCur++){
									if (map[XCur][YCur]!=null){
										Integer[] top = new Integer[]{};
										Integer[] bottom = new Integer[]{};
										Integer[] left = new Integer[]{};
										Integer[] right = new Integer[]{};
										String topID = "";
										String bottomID = "";
										String leftID = "";
										String rightID = "";
										//left
										if (YCur-1>=0){
											if (map[XCur][YCur-1]!=null){
												left=map[XCur][YCur-1].right;
												leftID=map[XCur][YCur-1].ID;
											}
										}
										//top
										if (XCur-1>=0){
											if (map[XCur-1][YCur]!=null){
												top=map[XCur-1][YCur].bottom;
												topID=map[XCur-1][YCur].ID;
											}
										}
										//right
										if (YCur+1<YCords){
											if (map[XCur][YCur+1]!=null){
												right=map[XCur][YCur+1].left;
												rightID=map[XCur][YCur+1].ID;
											}
										}
										//bottom
										if (XCur+1<XCords){
											if (map[XCur+1][YCur]!=null){
												bottom=map[XCur+1][YCur].top;
												bottomID=map[XCur+1][YCur].ID;
											}
										}
										map[XCur][YCur].tick(top, bottom, left, right, topID, bottomID, leftID, rightID);
									}
								}
							}
							viewer.repaint();
							cc++;
						}
					}
					if (System.currentTimeMillis()-lastTime>1000){
						if (cc>fps && fps>30){
							fps--;
						}
						if (cc<fps){
							fps++;
						}
						fc = 1000/(fps+1);
						System.out.println("Frames: "+(cc-1));
						cc = 1;
						lastTime = System.currentTimeMillis();
					}
				}
			}
		};
		reRender.start();
	}
}
class Gate{
	public static Image paintClear(){
		BufferedImage GateImage = new BufferedImage(100,100,BufferedImage.TYPE_INT_RGB);
		Graphics g = GateImage.getGraphics();
		g.setColor(Color.BLACK);
		g.fillRect(0, 0, 99, 99);
		g.setColor(Color.green);
		g.drawRect(0,0,99,99);
		return GateImage;
	}
	public Image paint(){
		BufferedImage GateImage = new BufferedImage(100,100,BufferedImage.TYPE_INT_RGB);
		
		return GateImage;
	}
	public Integer[] top = new Integer[]{};
	public Integer[] bottom = new Integer[]{};
	public Integer[] left = new Integer[]{};
	public Integer[] right = new Integer[]{};
	public String ID = "Clear Gate";
	public JMenu getMenu(){
		JMenu main = new JMenu(ID);
		return main;
	};
	public void click(){}
	public void tick(Integer[] top, Integer[] bottom, Integer[] left, Integer[] right, String topID, String bottomID, String leftID, String rightID){}
}
class GateSelect extends JPopupMenu{
	public GateSelect(final int x, final int y, final MainEngine e){
		JMenu Default = new JMenu("Default");
			JMenuItem clear = new JMenuItem("Clear");
			clear.addActionListener(new ActionListener(){
				@Override
				public void actionPerformed(ActionEvent arg0) {
					// TODO Auto-generated method stub
					e.map[x][y]=null;
				}});
			Default.add(clear);
			JMenuItem test = new JMenuItem("Test");
			test.addActionListener(new ActionListener(){
				@Override
				public void actionPerformed(ActionEvent arg0) {
					e.map[x][y]=new Gate(){
						boolean left_ = false;
						boolean right_ = false;
						boolean top_ = false;
						boolean bottom_ = false;
						public Image paint(){
							BufferedImage GateImage = new BufferedImage(100,100,BufferedImage.TYPE_INT_RGB);
							Graphics g = GateImage.getGraphics();
							g.setColor(Color.RED);
							if (top_){
								g.fillRect(2,2,97,2);
							}
							if (bottom_){
								g.fillRect(2,96,97,2);
							}
							if (left_){
								g.fillRect(2, 2, 2, 97);
							}
							if (right_){
								g.fillRect(96,2,2,97);
							}
							g.setColor(Color.WHITE);
							g.drawString("Hallo World!", 25, 25);
							g.setColor(Color.BLUE);
							g.drawRect(0,0,99,99);
							return GateImage;
						}
						public void tick(Integer[] top, Integer[] bottom, Integer[] left, Integer[] right, String topID, String bottomID, String leftID, String rightID){
							this.top_=top.length>0;
							this.bottom_=bottom.length>0;
							this.left_=left.length>0;
							this.right_=right.length>0;
							super.top = new Integer[]{1};
							super.bottom = new Integer[]{1};
							super.left = new Integer[]{1};
							super.right = new Integer[]{1};
						}
					};
				}});
			Default.add(test);
			JMenuItem redWire = new JMenuItem("Red Wire");
			redWire.addActionListener(new ActionListener(){
				@Override
				public void actionPerformed(ActionEvent arg0) {
					// TODO Auto-generated method stub
					e.map[x][y]=new Gate(){
						boolean left_ = false;
						boolean right_ = false;
						boolean top_ = false;
						boolean bottom_ = false;
						int left = 0;
						int right = 0;
						int top = 0;
						int bottom = 0;
						public Image paint(){
							BufferedImage GateImage = new BufferedImage(100,100,BufferedImage.TYPE_INT_RGB);
							Graphics g = GateImage.getGraphics();
							g.setColor(Color.WHITE);
							g.fillRect(0,0,99,99);
							g.setColor(Color.RED);
							if (top_){
								g.fillRect(45, 1, 10, 49);
							}
							if (bottom_){
								g.fillRect(45, 50, 10, 99);
							}
							if (left_){
								g.fillRect(1, 45, 49, 10);
							}
							if (right_){
								g.fillRect(50, 45, 99, 10);
							}
							g.setColor(Color.CYAN);
							g.drawRect(0,0,99,99);
							return GateImage;
						}
						public JMenu getMenu(){
							String[] sides = new String[]{"Clear","To Top","To Right","To Bottom","To Left"};
							JMenu sel = new JMenu(super.ID);
								JMenu topM = new JMenu("Top | "+sides[this.top]);
									JMenuItem topToTop = new JMenuItem("set to Top");
									topToTop.addActionListener(new ActionListener(){
										@Override
										public void actionPerformed(ActionEvent arg0) {
											// TODO Auto-generated method stub
											top = 1;
										}});
									JMenuItem topToRight = new JMenuItem("set to Right");
									topToRight.addActionListener(new ActionListener(){
										@Override
										public void actionPerformed(ActionEvent arg0) {
											// TODO Auto-generated method stub
											top = 2;
										}});
									JMenuItem topToBottom = new JMenuItem("set to Bottom");
									topToBottom.addActionListener(new ActionListener(){
										@Override
										public void actionPerformed(ActionEvent arg0) {
											// TODO Auto-generated method stub
											top = 3;
										}});
									JMenuItem topToLeft = new JMenuItem("set to Left");
									topToLeft.addActionListener(new ActionListener(){
										@Override
										public void actionPerformed(ActionEvent arg0) {
											// TODO Auto-generated method stub
											top = 4;
										}});
									JMenuItem topToClear = new JMenuItem("Clear");
									topToClear.addActionListener(new ActionListener(){
										@Override
										public void actionPerformed(ActionEvent arg0) {
											// TODO Auto-generated method stub
											top = 0;
										}});
									topM.add(topToTop);
									topM.add(topToRight);
									topM.add(topToBottom);
									topM.add(topToLeft);
									topM.add(topToClear);
								JMenu bottomM = new JMenu("Bottom | "+sides[this.bottom]);
									JMenuItem bottomToTop = new JMenuItem("set to Top");
									bottomToTop.addActionListener(new ActionListener(){
										@Override
										public void actionPerformed(ActionEvent arg0) {
											// TODO Auto-generated method stub
											bottom = 1;
										}});
									JMenuItem bottomToRight = new JMenuItem("set to Right");
									bottomToRight.addActionListener(new ActionListener(){
										@Override
										public void actionPerformed(ActionEvent arg0) {
											// TODO Auto-generated method stub
											bottom = 2;
										}});
									JMenuItem bottomToBottom = new JMenuItem("set to Bottom");
									bottomToBottom.addActionListener(new ActionListener(){
										@Override
										public void actionPerformed(ActionEvent arg0) {
											// TODO Auto-generated method stub
											bottom = 3;
										}});
									JMenuItem bottomToLeft = new JMenuItem("set to Left");
									bottomToLeft.addActionListener(new ActionListener(){
										@Override
										public void actionPerformed(ActionEvent arg0) {
											// TODO Auto-generated method stub
											bottom = 4;
										}});
									JMenuItem bottomToClear = new JMenuItem("Clear");
									bottomToClear.addActionListener(new ActionListener(){
										@Override
										public void actionPerformed(ActionEvent arg0) {
											// TODO Auto-generated method stub
											bottom = 0;
										}});
									bottomM.add(bottomToTop);
									bottomM.add(bottomToRight);
									bottomM.add(bottomToBottom);
									bottomM.add(bottomToLeft);
									bottomM.add(bottomToClear);
								JMenu leftM = new JMenu("left | "+sides[this.left]);
									JMenuItem leftToTop = new JMenuItem("set to Top");
									leftToTop.addActionListener(new ActionListener(){
										@Override
										public void actionPerformed(ActionEvent arg0) {
											// TODO Auto-generated method stub
											left = 1;
										}});
									JMenuItem leftToRight = new JMenuItem("set to Right");
									leftToRight.addActionListener(new ActionListener(){
										@Override
										public void actionPerformed(ActionEvent arg0) {
											// TODO Auto-generated method stub
											left = 2;
										}});
									JMenuItem leftToBottom = new JMenuItem("set to Bottom");
									leftToBottom.addActionListener(new ActionListener(){
										@Override
										public void actionPerformed(ActionEvent arg0) {
											// TODO Auto-generated method stub
											left = 3;
										}});
									JMenuItem leftToLeft = new JMenuItem("set to Left");
									leftToLeft.addActionListener(new ActionListener(){
										@Override
										public void actionPerformed(ActionEvent arg0) {
											// TODO Auto-generated method stub
											left = 4;
										}});
									JMenuItem leftToClear = new JMenuItem("Clear");
									leftToClear.addActionListener(new ActionListener(){
										@Override
										public void actionPerformed(ActionEvent arg0) {
											// TODO Auto-generated method stub
											left = 0;
										}});
									leftM.add(leftToTop);
									leftM.add(leftToRight);
									leftM.add(leftToBottom);
									leftM.add(leftToLeft);
									leftM.add(leftToClear);
								JMenu rightM = new JMenu("right | "+sides[this.right]);
									JMenuItem rightToTop = new JMenuItem("set to Top");
									rightToTop.addActionListener(new ActionListener(){
										@Override
										public void actionPerformed(ActionEvent arg0) {
											// TODO Auto-generated method stub
											right = 1;
										}});
									JMenuItem rightToRight = new JMenuItem("set to Right");
									rightToRight.addActionListener(new ActionListener(){
										@Override
										public void actionPerformed(ActionEvent arg0) {
											// TODO Auto-generated method stub
											right = 2;
										}});
									JMenuItem rightToBottom = new JMenuItem("set to Bottom");
									rightToBottom.addActionListener(new ActionListener(){
										@Override
										public void actionPerformed(ActionEvent arg0) {
											// TODO Auto-generated method stub
											right = 3;
										}});
									JMenuItem rightToLeft = new JMenuItem("set to Left");
									rightToLeft.addActionListener(new ActionListener(){
										@Override
										public void actionPerformed(ActionEvent arg0) {
											// TODO Auto-generated method stub
											right = 4;
										}});
									JMenuItem rightToClear = new JMenuItem("Clear");
									rightToClear.addActionListener(new ActionListener(){
										@Override
										public void actionPerformed(ActionEvent arg0) {
											// TODO Auto-generated method stub
											right = 0;
										}});
									rightM.add(rightToTop);
									rightM.add(rightToRight);
									rightM.add(rightToBottom);
									rightM.add(rightToLeft);
									rightM.add(rightToClear);
								sel.add(topM);
								sel.add(bottomM);
								sel.add(leftM);
								sel.add(rightM);
							return sel;
						}
						public void tick(Integer[] top, Integer[] bottom, Integer[] left, Integer[] right, String topID, String bottomID, String leftID, String rightID){
							super.ID = "Wire";
							super.top = new Integer[]{};
							super.bottom = new Integer[]{};
							super.left = new Integer[]{};
							super.right = new Integer[]{};
							if (this.top!=0){
								if (this.top==1){
									super.top = top;
								}
								if (this.top==2){
									super.right = top;
								}
								if (this.top==3){
									super.bottom = top;
								}
								if (this.top==4){
									super.left = top;
								}
							}
							if (this.left!=0){
								if (this.left==1){
									super.top = left;
								}
								if (this.left==2){
									super.right = left;
								}
								if (this.left==3){
									super.bottom = left;
								}
								if (this.left==4){
									super.left = left;
								}
							}
							if (this.bottom!=0){
								if (this.bottom==1){
									super.top = bottom;
								}
								if (this.bottom==2){
									super.right = bottom;
								}
								if (this.bottom==3){
									super.bottom = bottom;
								}
								if (this.bottom==4){
									super.left = bottom;
								}
							}
							if (this.right!=0){
								if (this.right==1){
									super.top = right;
								}
								if (this.right==2){
									super.right = right;
								}
								if (this.right==3){
									super.bottom = right;
								}
								if (this.right==4){
									super.left = right;
								}
							}
							top_ = topID.equalsIgnoreCase("Wire");
							bottom_ = bottomID.equalsIgnoreCase("Wire");
							left_ = leftID.equalsIgnoreCase("Wire");
							right_ = rightID.equalsIgnoreCase("Wire");
						}
					};
				}});
			Default.add(redWire);
		add(Default);
	}
}